home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / file-tra / rdist-6.1 / rdist-6 / rdist-6.1.0-linuxpl2 / src / filesys.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-27  |  10.5 KB  |  460 lines

  1. /*
  2.  * Copyright (c) 1983 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. static char RCSid[] = 
  36. "$Id: filesys.c,v 6.21 1993/03/27 20:05:44 mcooper Exp mcooper $";
  37.  
  38. static char sccsid[] = "@(#)filesys.c";
  39.  
  40. static char copyright[] =
  41. "@(#) Copyright (c) 1983 Regents of the University of California.\n\
  42.  All rights reserved.\n";
  43. #endif /* not lint */
  44.  
  45. /*
  46.  * This file contains functions dealing with getting info
  47.  * about mounted filesystems.
  48.  */
  49.  
  50. #include "defs.h"
  51. #include "filesys.h"
  52.  
  53. jmp_buf env;
  54.  
  55. /*
  56.  * Given a pathname, find the fullest component that exists.
  57.  * If statbuf is not NULL, set it to point at our stat buffer.
  58.  */
  59. char *find_file(pathname, statbuf, isvalid)
  60.     char *pathname;
  61.     struct stat *statbuf;
  62.     int *isvalid;
  63. {
  64.     static char last_pathname[MAXPATHLEN];
  65.     static char file[MAXPATHLEN];
  66.     static struct stat filestat;
  67.     register char *p;
  68.  
  69.     /*
  70.      * Mark the statbuf as invalid to start with.
  71.      */
  72.     *isvalid = 0;
  73.  
  74.     /*
  75.      * If this is the same pathname as the last time, and
  76.      * the file buffer is valid and we're doing the same stat()
  77.      * or lstat(), then set statbuf to the last filestat and 
  78.      * return the last file we found.
  79.      */
  80.     if (strcmp(pathname, last_pathname) == 0 && file[0]) {
  81.         if (statbuf)
  82.             statbuf = &filestat;
  83.         if (strcmp(pathname, file) == 0)
  84.             *isvalid = 1;
  85.         return(file);
  86.     }
  87.  
  88.     if ((int)strlen(pathname) > sizeof(file)+3) {
  89.         error("%s: Name to large for buffer.", pathname);
  90.             return((char *) NULL);
  91.     }
  92.  
  93.     /*
  94.      * Save for next time
  95.      */
  96.     (void) strcpy(last_pathname, pathname);
  97.  
  98.     if (*pathname == '/')
  99.             (void) strcpy(file, pathname);
  100.     else {
  101.         /*
  102.          * Ensure we have a directory (".") in our path
  103.          * so we have something to stat in case the file
  104.          * does not exist.
  105.          */
  106.             (void) strcpy(file, "./");
  107.         (void) strcat(file, pathname);
  108.     }
  109.  
  110.     while (lstat(file, &filestat) != 0) {
  111.         /*
  112.          * Trim the last part of the pathname to try next level up
  113.          */
  114.         if (errno == ENOENT) {
  115.             /*
  116.              * Trim last part
  117.              */
  118.             if (p = (char *) strrchr(file, '/'))
  119.                 *p = CNULL;
  120.             else
  121.                 /*
  122.                  * Couldn't find anything, so give up.
  123.                  */
  124.                 return((char *) NULL);
  125.             continue;
  126.         } else {
  127.             error("%s: lstat failed: %s", pathname, SYSERR);
  128.             return((char *) NULL);
  129.         }
  130.     }
  131.  
  132.     if (statbuf)
  133.         bcopy((char *) &filestat, (char *) statbuf, sizeof(filestat));
  134.  
  135.     /*
  136.      * If this file is a symlink we really want the parent directory
  137.      * name in case the symlink points to another filesystem.
  138.      */
  139.     if (S_ISLNK(filestat.st_mode))
  140.         if ((p = (char *) strrchr(file, '/')) && *p+1)
  141.             *p = CNULL;
  142.  
  143.     if (strcmp(pathname, file) == 0)
  144.         *isvalid = 1;
  145.  
  146.     return(file);
  147. }
  148.  
  149. #if defined(NFS_CHECK) || defined(RO_CHECK)
  150.  
  151. /*
  152.  * Find the device that "filest" is on in the "mntinfo" linked list.
  153.  */
  154. mntent_t *findmnt(filest, mntinfo)
  155.     struct stat *filest;
  156.     struct mntinfo *mntinfo;
  157. {
  158.     register struct mntinfo *mi;
  159.  
  160.     for (mi = mntinfo; mi; mi = mi->mi_nxt) {
  161.         if (mi->mi_mnt->me_flags & MEFLAG_IGNORE)
  162.             continue;
  163.         if (filest->st_dev == mi->mi_statb->st_dev)
  164.             return(mi->mi_mnt);
  165.     }
  166.  
  167.     return((mntent_t *) NULL);
  168. }
  169.  
  170. /*
  171.  * Is "mnt" a duplicate of any of the mntinfo->mi_mnt elements?
  172.  */
  173. int isdupmnt(mnt, mntinfo)
  174.     mntent_t *mnt;
  175.     struct mntinfo *mntinfo;
  176. {
  177.     register struct mntinfo *m;
  178.  
  179.     for (m = mntinfo; m; m = m->mi_nxt)
  180.         if (strcmp(m->mi_mnt->me_path, mnt->me_path) == 0)
  181.             return(1);
  182.  
  183.     return(0);
  184. }
  185.  
  186. /*
  187.  * Alarm clock
  188.  */
  189. void wakeup()
  190. {
  191.     debugmsg(DM_CALL, "wakeup() in filesys.c called");
  192.     longjmp(env, 1);
  193. }
  194.  
  195. /*
  196.  * Make a linked list of mntinfo structures.
  197.  * Use "mi" as the base of the list if it's non NULL.
  198.  */
  199. struct mntinfo *makemntinfo(mi) 
  200.     struct mntinfo *mi;
  201. {
  202.     FILE *mfp;
  203.     static struct mntinfo *mntinfo, *newmi, *m;
  204.     struct stat mntstat;
  205.     mntent_t *mnt;
  206.     int timeo = 310;
  207.  
  208.     if (!(mfp = setmountent(MOUNTED_FILE, "r"))) {
  209.         message(MT_NERROR, "%s: setmntent failed: %s", 
  210.             MOUNTED_FILE, SYSERR);
  211.         return((struct mntinfo *) NULL);
  212.     }
  213.  
  214.     (void) signal(SIGALRM, wakeup);
  215.     (void) alarm(timeo);
  216.     if (setjmp(env)) {
  217.         message(MT_NERROR, "Timeout getting mount info");
  218.         return((struct mntinfo *) NULL);
  219.     }
  220.  
  221.     mntinfo = mi;
  222.     while (mnt = getmountent(mfp)) {
  223.         debugmsg(DM_MISC, "mountent = '%s' (%s)", 
  224.              mnt->me_path, mnt->me_type);
  225.  
  226.         /*
  227.          * Make sure we don't already have it for some reason
  228.          */
  229.         if (isdupmnt(mnt, mntinfo))
  230.             continue;
  231.  
  232.         /*
  233.          * Get stat info
  234.          */
  235.         if (stat(mnt->me_path, &mntstat) != 0) {
  236.             message(MT_WARNING, "%s: Cannot stat filesystem: %s", 
  237.                 mnt->me_path, SYSERR);
  238.             continue;
  239.         }
  240.  
  241.         /*
  242.          * Create new entry
  243.          */
  244.         newmi = (struct mntinfo *) xcalloc(1, sizeof(struct mntinfo));
  245.         newmi->mi_mnt = newmountent(mnt);
  246.         newmi->mi_statb = 
  247.             (struct stat *) xcalloc(1, sizeof(struct stat));
  248.         bcopy((char *) &mntstat, (char *) newmi->mi_statb, 
  249.               sizeof(struct stat));
  250.  
  251.         /*
  252.          * Add entry to list
  253.          */
  254.         if (mntinfo) {
  255.             for (m = mntinfo; m && m->mi_nxt; m = m->mi_nxt);
  256.             m->mi_nxt = newmi;
  257.         } else
  258.             mntinfo = newmi;
  259.     }
  260.  
  261.     (void) alarm(0);
  262.     (void) endmountent(mfp);
  263.  
  264.     return(mntinfo);
  265. }
  266.  
  267. /*
  268.  * Given a name like /usr/src/etc/foo.c returns the mntent
  269.  * structure for the file system it lives in.
  270.  *
  271.  * If "statbuf" is not NULL it is used as the stat buffer too avoid
  272.  * stat()'ing the file again back in server.c.
  273.  */
  274. mntent_t *getmntpt(pathname, statbuf, isvalid)
  275.     char *pathname;
  276.     struct stat *statbuf;
  277.     int *isvalid;
  278. {
  279.     static struct mntinfo *mntinfo = NULL;
  280.     static struct stat filestat;
  281.     struct stat *pstat;
  282.     struct mntinfo *tmpmi;
  283.     register mntent_t *mnt;
  284.  
  285.     /*
  286.      * Use the supplied stat buffer if not NULL or our own.
  287.      */
  288.     if (statbuf) 
  289.         pstat = statbuf;
  290.     else
  291.         pstat = &filestat;
  292.  
  293.     if (!find_file(pathname, pstat, isvalid))
  294.             return((mntent_t *) NULL);
  295.  
  296.     /*
  297.      * Make mntinfo if it doesn't exist.
  298.      */
  299.     if (!mntinfo)
  300.         mntinfo = makemntinfo((struct mntinfo *) NULL);
  301.  
  302.     /*
  303.      * Find the mnt that pathname is on.
  304.      */
  305.     if (mnt = findmnt(pstat, mntinfo))
  306.         return(mnt);
  307.  
  308.     /*
  309.      * We failed to find correct mnt, so maybe it's a newly
  310.      * mounted filesystem.  We rebuild mntinfo and try again.
  311.      */
  312.     if (tmpmi = makemntinfo(mntinfo)) {
  313.         mntinfo = tmpmi;
  314.         if (mnt = findmnt(pstat, mntinfo))
  315.             return(mnt);
  316.     }
  317.  
  318.     error("%s: Could not find mount point", pathname);
  319.     return((mntent_t *) NULL);
  320. }
  321.  
  322. #endif /* NFS_CHECK || RO_CHECK */
  323.  
  324. #if    defined(NFS_CHECK)
  325. /*
  326.  * Is "path" NFS mounted?  Return 1 if it is, 0 if not, or -1 on error.
  327.  */
  328. int is_nfs_mounted(path, statbuf, isvalid)
  329.     char *path;
  330.     struct stat *statbuf;
  331.     int *isvalid;
  332. {
  333.     mntent_t *mnt;
  334.  
  335.     if ((mnt = (mntent_t *) getmntpt(path, statbuf, isvalid)) == NULL)
  336.         return(-1);
  337.  
  338.     if (strcmp(mnt->me_type, METYPE_NFS) == 0)
  339.         return(1);
  340.  
  341.     return(0);
  342. }
  343. #endif    /* NFS_CHECK */
  344.  
  345. #if    defined(RO_CHECK)
  346. /*
  347.  * Is "path" on a read-only mounted filesystem?  
  348.  * Return 1 if it is, 0 if not, or -1 on error.
  349.  */
  350. int is_ro_mounted(path, statbuf, isvalid)
  351.     char *path;
  352.     struct stat *statbuf;
  353.     int *isvalid;
  354. {
  355.     mntent_t *mnt;
  356.  
  357.     if ((mnt = (mntent_t *) getmntpt(path, statbuf, isvalid)) == NULL)
  358.         return(-1);
  359.  
  360.     if (mnt->me_flags & MEFLAG_READONLY)
  361.         return(1);
  362.  
  363.     return(0);
  364. }
  365. #endif    /* RO_CHECK */
  366.  
  367. /*
  368.  * Is "path" a symlink?
  369.  * Return 1 if it is, 0 if not, or -1 on error.
  370.  */
  371. int is_symlinked(path, statbuf, isvalid)
  372.     /*ARGSUSED*/
  373.     char *path;
  374.     struct stat *statbuf;
  375.     int *isvalid;
  376. {
  377.     static struct stat stb;
  378.  
  379.     if (!(*isvalid)) {
  380.         if (lstat(path, &stb) != 0)
  381.             return(-1);
  382.         statbuf = &stb;
  383.     }
  384.     
  385.     if (S_ISLNK(statbuf->st_mode))
  386.         return(1);
  387.  
  388.     return(0);
  389. }
  390.  
  391. /*
  392.  * Get filesystem information for "file".  Set freespace
  393.  * to the amount of free (available) space and number of free
  394.  * files (inodes) on the filesystem "file" resides on.
  395.  * Returns 0 on success or -1 on failure.
  396.  * Filesystem values < 0 indicate unsupported or unavailable
  397.  * information.
  398.  */
  399. int getfilesysinfo(file, freespace, freefiles)
  400.     char *file;
  401.     long *freespace;
  402.     long *freefiles;
  403. {
  404. #if    defined(STATFS_TYPE)
  405.     static statfs_t statfsbuf;
  406.     char *mntpt;
  407.     int t, r;
  408.  
  409.     /*
  410.      * Get the mount point of the file.
  411.      */
  412.     if ((mntpt = find_file(file, NULL, &t)) == NULL)
  413.         return(-1);
  414.  
  415.     /*
  416.      * Stat the filesystem (system specific)
  417.      */
  418. #if    STATFS_TYPE == STATFS_SYSV
  419.     r = statfs(mntpt, &statfsbuf, sizeof(statfs_t), 0);
  420. #endif
  421. #if    STATFS_TYPE == STATFS_BSD
  422.     r = statfs(mntpt, &statfsbuf);
  423. #endif
  424. #if    STATFS_TYPE == STATFS_OSF1
  425.     r = statfs(mntpt, &statfsbuf, sizeof(statfs_t));
  426. #endif
  427.  
  428.     if (r < 0) {
  429.         error("%s: Cannot statfs filesystem: %s.", mntpt, SYSERR);
  430.         return(-1);
  431.     }
  432.  
  433.     /*
  434.      * If values are < 0, then assume the value is unsupported
  435.      * or unavailable for that filesystem type.
  436.      */
  437.     if (statfsbuf.f_bavail >= 0)
  438.         *freespace = (statfsbuf.f_bavail * (statfsbuf.f_bsize / 512))
  439.                   / 2;
  440.  
  441.     /*
  442.      * BROKEN_STATFS means that statfs() does not set fields
  443.      * to < 0 if the field is unsupported for the filesystem type.
  444.      */
  445. #if    defined(BROKEN_STATFS)
  446.     if (statfsbuf.f_ffree > 0)
  447. #else
  448.     if (statfsbuf.f_ffree >= 0)
  449. #endif     /* BROKEN_STATFS */
  450.         *freefiles = statfsbuf.f_ffree;
  451.  
  452. #else    /* !STATFS_TYPE */
  453.  
  454.         *freespace = *freefiles = -1;
  455.  
  456. #endif    /* STATFS_TYPE */
  457.  
  458.     return(0);
  459. }
  460.